perm filename SPLAY.FAI[SAM,LCS]1 blob
sn#437774 filedate 1979-05-02 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00035 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00005 00002 TITLE PLAY
C00008 00003 SUBTTL Data Formats
C00009 00004 PLAY: 0
C00019 00005 ----- RPGSA RPG entry point
C00020 00006 ----- DOINIT Open files and initialize
C00025 00007 ----- MAINLP Main loop
C00027 00008 NSUBR TTYIN
C00031 00009 NSUBR ESCI Handle <ESC>I, also ALTCHK
C00035 00010 ----- DIE Flush anything still active and exit
C00036 00011 NSUBR RDMAIL Read mail and perhaps decide what to do
C00039 00012 NSUBR SAMINI Initialize the Samson Box.
C00047 00013 NSUBR SAMGO Start Samson Box
C00048 00014 NSUBR SIXMSG Process message from SIX
C00051 00015 ----- MINT - Print information (Samson Box interrupt)
C00054 00016 ----- MCDONE - Command buffer done (send another)
C00057 00017 ----- MRDONE - Read data done (send another)
C00058 00018 ----- MWDONE - Write data done (send to disk and setup next)
C00059 00019 ----- ADCDONE - ADC buffer done (send another)
C00060 00020 NSUBR MSGWAIT,CODE Wait for specified message type
C00063 00021 NSUBR GETSCM,COUNT Get SCM buffer (also GETAUX)
C00066 00022 NSUBR SNDSCM,COUNT Send command buffer to SAM (also SNDAUX)
C00070 00023 NSUBR SETOUT,COUNT Send data buffer to SAM (also SNDOUT)
C00072 00024 NSUBR SETADC,COUNT Send data buffer to ADC
C00073 00025 NSUBR ENDSCM Send special trailer buffer to SAM
C00075 00026 NSUBR RCVMSG Recieve message from SIX
C00076 00027 NSUBR SNDMSG,CODE,DATA,SIZE Send message to SIX (device)
C00078 00028 NSUBR SNDMS1,CODE Send one word message to SIX (device)
C00079 00029 NSUBR PRTMSG Print message
C00081 00030 NSUBR WAITON,CONDITIONS Wait for one of several events
C00083 00031 ----- INTSER Interrupt service routine
C00084 00032 NSUBR SNDINT Send interrupt to calling program
C00085 00033 NSUBR SWNUM Get number from switch name (from FCOPY)
C00088 00034 Typeout to arbitrary TTY, using NULMES
C00091 00035 Data area
C00100 ENDMK
C⊗;
TITLE PLAY
ENTRY PLAY
↓msgbug←←1 ;Message debugging (leave on)
↓intbug←←0 ;Interrupt debugging
↓ADSSAM←←3 ;Audio Switch channel for Samson Box.
ifndef membug,< ↓membug←←0 > ;Kludge to avoid top 32K of memory!!!!
↓tmoenb←←0 ;Enable timeout feature (if non-zero)
;;; PRINTS/A program to drive Samson Box from SAM file
;;;/
ifn intbug,< prints/⊗ Interrupt debugging code included.
/>
;;;ifn msgbug,< prints/⊗ Message printing code included.
;;;/>
ifn membug,< prints/******** Horrible kludge to skip top of memory included *****
/>
.INSERT HEADER.FAI[1,TVR]
.INSERT INTDEF.FAI[1,TVR]
.INSERT RPGDEF.FAI[1,TVR]
.INSERT MESDEF[SIX,MUS]
.INSERT DEVDEF[SIX,MUS]
.INSERT DACDEF[SIX,MUS]
.INSERT SAMDEF[SIX,MUS]
.LIBRARY TVRLIB.REL[SUB,SYS]
EXTERNAL JOBCNI,JOBAPR
;Parameters
↓MAXBFS←←=10 ;Maximum number of buffers which may be used for SAM
↓MSGMSZ←←=64+3 ;Maximum message size
↓TAILSZ←←=28 ;Size of trailer (to make sure command buffer done
;means command list is done)
;Definitions
↓RET←1
↓RET2←RET+1
↓T←3
↓T2←T+1
↓A←4
↓B←A+1
↓SCMCHN←←1 ;Input (SCM) file
↓AUXCHN←←3 ;Read data (SDA) file
↓OUTCHN←←2 ;Write data (SDA) file
↓SIXCHN←←4 ;SIX channel
↓SAMCHN←←5 ;SAM interlock device
↓ADCCHN←←6 ;ADC interlock device
↓DEVWAI←←1000 ;Wait for device
↓DEVNWA←←400 ;Take error return if busy (No wait)
↓SIXDEV←←SYSDEV ;Handy alias
;Bits for CONOA SAM, ('Sam ConoA')
↓SCAHLT←←200000 ;Stop clock ('halt')
↓SCAGO ←←400000 ;Start clock ('go')
↓SCASTP←←600000 ;Cause one tick ('step')
↓SCACLT←←100000 ;Reset tick counter ('clear ticks')
↓SCAPRO←←004000 ;Permit processing ticks
↓SCAUPD←←010000 ;Update ticks only
↓SCAMR ←←000010 ;Master reset
;Fields for CONOB SAM,
↓DR20B←←27 ;Select one 20 bit samples/word
;Special commands
↓CLRPAS←←430 ;Clear pass counter, linger of 0
↓SCMNOP←←0 ;NOP command
SUBTTL Data Formats
;Letters from MAIL UUO
COMMENT ⊗
Job number of caller ;0
unused ;1
unused ;2
SIXBIT/function/ ;3
TTY number ;4
Interrupt bit to send on completion ;5
unused (or arg 1) ;6
unused (or arg 2) ;7
SIXBIT/device/ ;10
unused ;11
SIXBIT/file/ ;12
SIXBIT/ext/ ;13
unused ;14
SIXBIT/pppn/ ;15
⊗;
↓MLJOB←←0 ;Job number
↓MLCMD←←3 ;Command name
↓MLINT←←5 ;Interrupt bits
↓MLIOSP←←10 ;I/O specification index
↓MLARG1←←6
↓MLARG2←←7
PLAY: 0
START: SKIPA
JRST RPGSA ;RPG starting address
RESET
MOVE P,PDLIOWD ;Set up stack
PUSHJ P,[ ;Do primary initialization
INIT1: MOVE 1,JOBFF ;Core down perhaps
SKIPN JOBDDT↑ ;Debugging?
CORE 1, ; No, then we don't need symbols
JFCL
SETZM BEGZER ;Zero non-constant data area
MOVE 1,[XWD BEGZER,BEGZER+1]
BLT 1,ENDZER
SETOM PACKED ;Assume packed read data at first
;Initialize for type out
MOVEI 1,TYOSIZ ;Number of bytes in buffer
MOVEM 1,TYOLFT
MOVE 1,[POINT 7,TYOBUF] ;Point at beginning of buffer
MOVEM 1,TYOPTR
POPJ P,]
MOVSI 1,'TTY' ;Output to normal TTY
MOVEM 1,TYOTTY
MOVEI 1,1 ;Assume one play
MOVEM 1,RPTCNT
RESCAN RESCNT ;Get at command arguments, count→2
RESLOO: SOSL RESCNT ;Any characters left in arguement
INCHSL 1 ;Get it then
JRST START1 ;None left, ask user explicately
CAIN 1,";" ;Beginning of arguments?
JRST START0 ; Yes, start without prompt
CAIE 1,12 ;End of line?
JRST RESLOOP ; No, go back for more
START1: SKIPLE RESCNT ;Flush any extra crud (might have been
INCHSL 1 ;hacking DDT
SKIPA
JRST START1 ;More crud to flush
;; OUTSTR[ASCIZ/
;;*/]
START0: ;First, read output file, but might also be input file
;Read input file
SETZM OUTFILE ;Mark as unused
SETZM AUXFILE ;Mark as unused
JRST DOINIT
;GO PLAY TEST.SAM
CALL RDIOSP↑,<[OUTBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SAM/]>
JRST START1 ;Blank line, give out a prompt
CAIN 1,"/" ;How about switch processing
PUSHJ P,DOSWITCH ; Sure, try it
CAIN 1,15 ;CR?
PUSHJ P,CMDGET ; Yes, read ever present LF
CAIE 1,"←"
JRST [ ;Yes, use same file with different extensions
PUSH P,INBLK+2 ;Save buffer header
MOVE 2,[XWD OUTBLK+1,INBLK+1] ;and copy file spec.
BLT 2,INFILE+3
POP P,INBLK+2
HLRZ 2,OUTFILE+1 ;If default output is given
CAIN 2,'TEST' ;then use default input
MOVEI 2,'SAM' ;extension
HRLM 2,INFILE+1
SETZM OUTFILE ;Mark as unused
MOVE 2,OUTSIZ ;Set buffer size
MOVEM 2,SCMSIZ
JRST AUXCHK ] ;Don't ask for input
GETIN: CALL RDIOSP↑,<[INBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SAM/]>
JRST START3 ;Blank, must be confused
AUXCHK: CAIN 1,"/" ;How about some switch processing?
PUSHJ P,DOSWITH ; Sure, at least think about it
CAIN 1,","
JRST[ CALL RDIOSP,<[AUXBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SDA/]>
JRST START3
JRST AUXCHK]
CAIN 1,"?"
JRST HELPME
CAIN 1,15 ;Flush ever present LF after CR
PUSHJ P,CMDGET
CAIE 1,12 ;Better be end of line
START3: JRST [ CAIN 1,"?" ;Need help?
JRST HELPME ; Yes
OUTSTR[ASCIZ/
I don't understand, try again. Type ? for help./]
JRST START1 ]
JRST DOINIT
HELPME: OUTSTR[
HELPMSG: ASCIZ $
This program sends commands from a disk file to the Samson Box. It
expects to see a file name as input. You may also include the following
switches which affect the way the program works:
/REPEAT=3 Repeat 3 times
/PAUSE=2 Pause 2 seconds between repeats (Doesn't work)
/WAIT If someone is already using SAM, wait for him/her to finish.
/NOMAP Don't switch the console speaker to SAM channel 1
/TAPE Wait until 'GO' is typed before playing
/HOG Don't let go of SAM between plays
/LOCK Lock job in core
/MEMDEB Prints memory buffer addresses
/EXIT Exit after playing specified repetitions.
/DEBUG Causes debugging information to be printed
/BUFSIZ Set buffer size in 128 wd records
/BUFCNT Set number of buffers to use
/ADC Take input from ADC instead of disk
/ADSIZE Specify size of ADC's buffer
/OVERWR Over-writes output file. This makes it go faster.
/HELP Print this cruft
For example:
.R SAMPHA
*SOLFEG.SAM[SAM,MUS]/EXIT
Plays SOLFEG.SAM[SAM,MUS] once and then exits to the monitor.
.R SAMPHA;TEST20/REPEAT=5/WAIT
Waits for SAM to be available and plays TEST20.SCM (from your current
disk area) five times.
$]
JRST START1 ;Now, try again
;Switch processing
DOSWIT: CALL SWNUM ;Get switch by number
SETZ RET, ;Default argument of 0
CAIE 0,"=" ;Is there a numeric argument?
JRST NOARGS
CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
SKIPA
NOARGS: TLO RET2,400000
XCT SWXCT(RET2)
MOVE RET,0
CAIE RET,"/" ;Another switch?
POPJ P, ; No, done
JRST DOSWIT ;Repeat until they've all been eaten
;Switches known herein
SWTAB: SIXBIT/REPEAT/
SIXBIT/PAUSE/
SIXBIT/WAIT/
SIXBIT/NOMAP/
SIXBIT/EXIT/
SIXBIT/HELP/
SIXBIT/DEBUG/
SIXBIT/BUFSIZ/
SIXBIT/BUFCNT/
SIXBIT/TAPE/
SIXBIT/HOG/
SIXBIT/LOCK/
SIXBIT/MEMDEB/
SIXBIT/PACKED/
SIXBIT/UNPACK/
SIXBIT/ADC/
SIXBIT/OVERWR/
SIXBIT/ADSIZE/
↓SWCNT←←.-SWTAB
SWXCT: PUSHJ P,[ ;REPEAT
SKIPL RET2 ;Argument given?
MOVEM RET,RPTCNT ; Yes, store it
POPJ P,]
PUSHJ P,[ ;PAUSE (cop-out)
OUTSTR[ASCIZ/Pause feature not implemented
MOVEM RET,WAITCNT
/]↔ POPJ P,]
SETCMM WAITFL ;WAIT - Always wait for SAM
SETCMM NOMAP ;NOMAP - Don't map the audio switch!
SETCMM ONCE ;ONCE - Play once and leave
OUTSTR HELPMSG ;HELP
SETCMM DEBUG ;DEBUG - Print debugging information
PUSHJ P,[ ;BUFSIZ
IMULI RET,=128
SKIPG RET2 ;Argument given?
POPJ P,
SKIPE AUXFIL ;For Auxillary?
JRST[ MOVEM RET,AUXSIZ ; Yes, store it
POPJ P,]
SKIPE INFILE ;For Input?
JRST[ MOVEM RET,SCMSIZ ; Yes, store it
POPJ P,]
SKIPE OUTFILE ;For Output?
JRST[ MOVEM RET,OUTSIZ ; Yes, store it
POPJ P,]
POPJ P,]
PUSHJ P,[ ;BUFCNT
SKIPL RET2 ;Argument given?
MOVEM RET,NBUFS ; Yes, store it
POPJ P,]
SETCMM TAPEFL ;TAPE - wait for GO before playing
SETCMM GRABBY ;HOG - don't let go of SAM
SETCMM LOCKFL ;LOCK - lock program in core
SETCMM MEMDEB ;MEMDEB - print memory buffer addresses
SETOM PACKED ;PACKED - packed input file (16 bit)
SETZM PACKED ;UNPACKED - unpacked input file (20 bit)
SETOM ADCFLG ;ADC - Enable ADC operation
SETOM OVERWR ;OVERWR - Overwrite, don't create new file
PUSHJ P,[ ;ADSIZE - Set size of ADC buffer
IMULI RET,=128
SKIPLE RET2 ;Argument given?
MOVEM RET,AUXSIZ ; Yes, store it
POPJ P,]
;----- RPGSA ;RPG entry point
RPGSA: MOVE P,PDLIOWD ;Set up stack
PUSHJ P,INIT1 ;Do primary initialization
MOVEM RPGDEV,INDEV
MOVEM RPGFIL,INFILE
MOVEM RPGEXT,INFILE+1
MOVEM RPGPPN,INFILE+3
CAIG RPGLIN,200 ;Check line number
MOVEM RPGLIN,TYOTTY ;If OK, set TTY number
; JRST DOINIT
;fall thru to next page
;----- DOINIT ;Open files and initialize
;fall thru from previous page
BEGIN DOINIT
↑DOINIT: INIT SIXCHN,17
SIXBIT/SIX/
0
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't INIT device SIX, you can't run the Samson Box./]]>,TYOOP
JRST DIE]
OPEN SCMCHN,INBLK ;Open input side first (not really the
;right thing if input=output file, due
;to timing loss if two people try to
;update the same file
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
CALL WRSIX↑,INBLK+1,TYOOP
JRST DIE]
MOVE 1,INFILE+3 ;Save PPN
LOOKUP SCMCHN,INFILE
JRST[ MOVEM 1,INFILE+3 ;Restore PPN
CALL WRASCZ↑,<[[ASCIZ/Can't find file: /]]>,TYOOP
CALL WRIOSP↑,<[INBLK+1]>,TYOOP
MOVE 1,INFILE ;Check for HELP
CAME 1,[SIXBIT/HELP/]
JRST DIE
CALL DOCRLF
CALL WRASCZ↑,<[HELPMSG]>,TYOOP
JRST DIE]
EXCH 1,INFILE+3 ;Restore PPN, get count
MOVS 1,1 ;Unfungle count
MOVNM 1,INWC ;Set word count
SKIPN AUXFIL ;Open aux. input?
JRST SKPAUX
OPEN AUXCHN,AUXBLK ;Open input side first (not really the
;right thing if input=output file, due
;to timing loss if two people try to
;update the same file
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
CALL WRSIX↑,INBLK+1,TYOOP
JRST DIE]
MOVE 1,AUXFILE+3 ;Save PPN
LOOKUP AUXCHN,AUXFILE
JRST[ MOVEM 1,AUXFILE+3 ;Restore PPN
CALL WRASCZ↑,<[[ASCIZ/Can't find file: /]]>,TYOOP
CALL WRIOSP↑,<[AUXBLK+1]>,TYOOP
JRST DIE]
EXCH 1,AUXFILE+3 ;Restore PPN, get count
MOVS 1,1 ;Unfungle count
MOVNM 1,AUXWC ;Set word count
SKPAUX: SKIPN OUTFIL ;Open output?
JRST SKPOUT
OPEN OUTCHN,OUTBLK
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
CALL WRSIX↑,INBLK+1,TYOOP
JRST DIE]
SKIPN OVERWR ;Overwrite mode?
JRST NOTOVR ; No, create new file
MOVE 1,OUTFIL+3 ;Save PPN
LOOKUP OUTCHN,OUTFILE
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't find file to overwrite: /]]>
CALL WRFILN↑,<[OUTBLK+1]>,TYOOP
JRST DIE]
MOVEM 1,OUTFIL+3 ;Replace PPN
NOTOVR: ENTER OUTCHN,OUTFILE
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't (over)write file: /]]>,TYOOP
CALL WRFILN↑,<[OUTBLK+1]>,TYOOP
JRST DIE]
SKPOUT: MOVE 1,AUXFIL ;Check for read data active
OR 1,ADCFLG
MOVEM 1,RDAFLG
PJOB 1, ;Get this job's number
MOVEM 1,THISJOB
MOVEI RET,INTSER ;Set interrupt service routine
MOVEM RET,JOBAPR
INTMSK [0] ;Don't allow any interrupts
MOVE RET,[INTTTY!INTMAIL!INTTTI!INTSIX]
INTENB RET, ;Enable interrupts
movsi ret,'TTY' ;Check for TTY
came ret,tyotty
jrst [skpme ; No, wait for mail
jrst mainlp
call rdmail
jrst mainlp]
call saminit
skipe tapefl ;Tape mode?
jrst mainlp ; Yes, wait
skipe samrdy ;Is it ready
call samgo ; Yes, start it going
; JRST MAINLP
BEND DOINIT
;fall thru to next page
;----- MAINLP ;Main loop
;fall thru from previous page
MAINLP:
CLKINT [=60*=60*1] ;Wait 1 minute(s) before giving up
ifn intbug,< outchr ["⊗"] >
CALL WAITON,<[INTTTY!INTMAIL!INTCLK!INTTTI!INTSIX]]>
MOVE A,PENDING ;OR in any pending interrupts
TLNE A,(INTTTY) ;TTY input interrupt
JRST[ CALL TTYIN ; Yes, dealt with it
MOVSI A,(INTTTY)
ANDCAB A,PENDING
JRST .+1]
TLNE A,(INTTTI)
CALL ESCI
TLNE A,(INTMAIL) ;Mail received?
JRST[ CALL RDMAIL ; Yes, read it
SETZM PENDING
JRST MAINLP] ; Go back for more
TRNE A,INTSIX ;SIX message?
JRST[ CALL RCVMSG ; Yes, handle generally
CALL SIXMSG
MOVEI A,INTSIX
ANDCAB A,PENDING ; SIX message is no longer pending
JRST .+1]
TLNE A,(INTCLK)
JRST[
MOVSI A,(INTCLK)
ANDCAB A,PENDING ; Timeout was handled
IFE TMOENB,<
SKIPE SAMRDY ;Is SAM ready to run or running?
>;IFE TMOENB
IFN TMOENB,<
SKIPE TAPEFL ;Don't timeout in tape mode!
>;IFN TMOENB
JRST .+1 ; Yes, ignore time-out for now.
CALL WRASCZ↑,<[[ASCIZ/Timeout - Aborting/]]>,TYOOP
JRST DIE]
JUMPE A,MAINLP ;All interrupts serviced
CALL WRASCZ↑,<[[ASCIZ/Unexpectd return from WAITON, ignoring./]]>,TYOOP
CALL DOCRLF
SETZM PENDING
JRST MAINLP
NSUBR TTYIN
SNEAKS RET, ;Get first character, if any
POPJ P, ; False alarm
CAIN RET," " ;Eat any stray spaces
JRST[ INCHRS RET ; If we can
POPJ P, ; Cheap insurance
JRST TTYIN]
CAIE RET,"g"
CAIN RET,"G" ;G is for Go from TAPE switch
JRST[ CALL EATLIN ; Eat the rest of the line
SKIPN SAMRDY ; Is it ready?
JRST[ OUTSTR[ASCIZ/Not ready, need a repeat count first.
/]↔ JRST TTYIN]
CALL SAMGO ; Start it running
JRST TTYIN] ; Look for more crud
CAIN RET,";" ;For talking
JRST[ CALL EATLIN
JRST TTYIN] ; Look for more crud
CAIE RET,"y"
CAIN RET,"Y" ;Y means wait for box (if not present)
JRST[ CALL EATLIN
SETOM WAITFL ; Now, always wait
JRST RETRY] ; And try again
CAIE RET,"n"
CAIN RET,"N" ;N means give up
JRST[ CALL EATLIN
JRST DIE]
CAIE RET,12 ;<lf>
CAIN RET,15 ;<cr>
JRST[ CALL EATLIN ; Flush and leave
JRST DIE]
CAIN RET,175 ;<alt>
CALL ALTCHK ; This will print a nice message
CAIN RET,"/" ;Is it a switch
JRST[ INCHWL RET ; Yes, curious, but we can do it
CALL DOSWITCH
JRST ENDCHK]
;If none of the above, assume it's a number (ha,ha)
CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
MOVEM RET,RPTCNT ;Set repeat count
CAIN 0,"/" ;Switch?
CALL DOSWITH ; Why not try.
CAIE 0,"," ;Wait time given?
JRST ENDCHK ; No, check for end of line
CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
MOVEM RET,WAITIM ;Set pause time
ENDCHK: CAIN 0,15 ;Is it a <cr>
INCHWL 0 ; Yes, eat companion <lf>
CAIE 0,12 ;Is it a <lf>
JRST[ OUTSTR[ASCIZ/???
Number of times to play (or <ALT> to quit): /]
POPJ P,]
RETRY: SKIPG RPTCNT ;Repeat count positive?
POPJ P, ; No, don't bother further
CALL SAMINIT ;Get it ready to go again
SKIPN TAPEFL ;Taping?
CALL SAMGO ; No, start it now!
POPJ P, ;Go for more stuff
EATLIN: INCHRS RET ;Consume to <cr> or <lf>
POPJ P, ; Hmmm, end of the line came a bit early
CAIN RET,12
POPJ P,
CAIE RET,175 ;<alt>?
JRST EATLIN ; No, eat some more crud from line
ALTBYE: CALL WRASCZ↑,<[[ASCIZ/Flushed/]]>,TYOOP
JRST DIE
SUBREND TTYIN
NSUBR ESCI ;Handle <ESC>I, also ALTCHK
CALL WRASCZ↑,<[[ASCIZ/<esc>I - Aborting.../]]>,TYOOP
SETZM PENDING
CALL DOCRLF
CALL SNDMS1,<[MCONIA,,SAMDEV]>
CALL SNDMS1,<[MCONIB,,SAMDEV]>
CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT]]>,<[1]> ;Stop its clock
CALL MSGWAIT,<[MCONIA,,SAMDEV]>
CALL SIXMSG
CALL MSGWAIT,<[MCONIB,,SAMDEV]>
CALL SIXMSG
MOVSI RET,'TTY' ;Is this run from console mode?
CAME RET,TYOTTY
JRST DIE ; No, exit quickly
CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT]]>,<[1]> ;Stop its clock
SKIPE LOCKFL ;Was it maybe locked?
UNLOCK ; Yes, unlock it!
CMDLP: CALL WRASCZ↑,<[[ASCIZ/Dump delay_memory from (<ALT> to exit): /]]>,TYOOP
CALL TYOFLUSH
CALL RDINT↑,<[8]>,<[PUSHJ P,CMDGET]>
CAIN 0,175
JRST DIE
DMPSIZ←←8*8
MOVE B,RET ;Save address for printing purposes
CAIN 0,15 ;CR?
PUSHJ P,CMDGET ; Yes, get corresponding LF
HRLI B,-DMPSIZ
MOVEM B,MSGDAT
CALL SNDMSG,<[MDMRW,,SAMDEV]>,<[0]>,<[1+DMPSIZ]>
;Write randomness and get data from memory
CALL MSGWAIT,<[MDMRW,,SAMDEV]>
;Wait for read data
CALL SNDMSG,<[MDMWR,,SAMDEV]>,<[0]>,<[1+DMPSIZ]>
;Write original data back
MOVSI A,-DMPSIZ ;Setup to dump to terminal
DMPLP: TRNE A,7 ;Time to start new line?
JRST SKPADR ; No, do more will fit on this line
TRNE A,-1 ;First line?
CALL DOCRLF ; No, CRLF between lines
HRRZ RET,A
ADDI RET,(B)
CALL WROCT↑,RET,<[6]>,TYOOP ;Print address
SKPADR: MOVEI RET,11 ;TAB to separate
XCT TYOOP
CALL WROCT↑,<MSGDAT+1(A)>,<[7]>,TYOOP ;Print a location
AOBJN A,DMPLP ;Repeat for each word in memory
CALL DOCRLF ;Final CRLF
JRST CMDLP
SUBREND ESCI
NSUBR ALTCHK ;Check for <alt>
MOVSI RET,INTTTY ;We've look at this one
ANDCAM RET,PENDING
SNEAKS RET, ;Is there anything there?
POP0J ; No, forget it!
CAIE RET,175 ;Is it an <alt>
POP0J ; No, ignore for now.
CALL WRASCZ↑,<[[ASCIZ/Flushed/]]>,TYOOP
JRST DIE
SUBREND ALTCHK
;----- DIE ;Flush anything still active and exit
DIE: CALL DOCRLF ;Flush out any messages
QDIE: RESET ;Flush any I/O
CLRBFI
HRRZ 1,120 ;GET STARTING ADDRESS FOR RETURN HOME
JRST (1) ;GO THERE.
;; EXIT 1, ;Leave quickly
;NSUBR RDMAIL ;Read mail and perhaps decide what to do
RDMAIL: SRCV MAILBOX ;Is there mail?
POPJ P, ; False alarm, just return
MOVE RET,MAILBOX+MLCMD ;Get command
CAMN RET,[SIXBIT/ABORT/] ;Abort command?
JRST QDIE ; Yes, flush everything and leave
CAMN RET,[SIXBIT/REINIT/] ;Restart?
JRST[ MOVE RPGDEV,MAILBOX+MLIOSP ;Setup RPG ACs
MOVE RPGFIL,MAILBOX+MLIOSP+2
MOVE RPGEXT,MAILBOX+MLIOSP+3
MOVE RPGPPN,MAILBOX+MLIOSP+5
MOVE RPGLIN,TYOTTY
RESET
JRST RPGSA ]
CAMN RET,[SIXBIT/PLAY/] ;Start or continue playing
JRST[ CALL PLAYARGS ; Setup arguments for PLAY
SKIPN SAMRDY ; Already setup?
CALL WSAMINIT ; No, initialize it
SKIPN SAMRUN ; Already running?
CALL SAMGO ; No, Start it running
POPJ P,] ; Done
CAMN RET,[SIXBIT/WAIT/]
JRST[ CALL PLAYARGS ; Setup arguments for PLAY
SKIPN SAMRDY ; Already setup?
CALL WSAMINIT ; No, initialize it
SKIPN SAMRUN ; Already running?
CALL SAMGO ; No, Start it running
POPJ P,] ; Done
CAMN RET,[SIXBIT/SAMINI/]
JRST[ CALL PLAYARGS ; Setup arguments for PLAY
SKIPN SAMRDY ; Already running?
CALL SAMINIT ; No, Start it running
POPJ P,] ; Done
CAMN RET,[SIXBIT/GO/]
JRST[ CALL PLAYARGS ; Setup arguments for PLAY
SKIPN SAMRUN ; Already running?
CALL SAMGO ; No, Start it running
POPJ P,] ; Done
CALL WRASCZ↑,<[[ASCIZ/Unknown command: /]]>,TYOOP
CALL WRSIX↑,MAILBOX+MLCMD,TYOOP
CALL DOCRLF
POPJ P,
;Setup arguments for PLAY or WAIT
PLAYAR: MOVE RET,MAILBOX+MLARG2 ; Set wait time, if any
MOVEM RET,WAITIM
MOVE RET,MAILBOX+MLARG1 ; Add number of times to play
EXCH RET,RPTCNT ; Preserve whether running before
ADDM RET,RPTCNT
POPJ P,
NSUBR SAMINI ;Initialize the Samson Box.
SKIPN WAITFL ;Always wait?
SKIPA 1,[DEVNWA] ; No, Don't wait
↑WSAMIN: MOVEI 1,DEVWAI ;Wait for device
INIT SAMCHN,(1) ;Get the Box
SIXBIT/SAM/
0
JRST[ CAIN 1,DEVWAI+17 ;Were we waiting?
JRST NOSAM
CALL WRASCZ↑,<[[ASCIZ/SAM is busy, will you wait? /]]>,TYOOP
CALL DOCRLF
POP0J]
SKIPN ADCFLG ;Get ADC?
JRST SKPADC
INIT ADCCHN,
SIXBIT/ADC/
0
JRST[ CALL WRASCZ↑,<[[ASCIZ/Can't INIT ADC (it is unavailable). /]]>,TYOOP
JRST DIE ]
SKPADC:
;;; PRINTS/Not zeroing delay memory yet!
;;;/
CALL SNDMS1,<[MDBLAST,,SAMDEV]> ;Flush any old crud which may be running
CALL MSGWAIT,<[MDBLAST,,SAMDEV]> ;Wait for it
SKIPE LOCKFL ;Lock in core?
LOCK ; Yes!
ifn membug,<
;Eat whole top of memory!!!!!
call sndmsg,<[mgbuf,,sixdev]>,<[[=32*=1024]]>,<[1]>
call msgwait,<[mgbuf,,sixdev]>
pushp msgdat
skipl msgdat
jrst[ skipe scmwcma
jrst .+1
call wrascz↑,<[[asciz/This will probably lose!
/]]>,tyoop
jrst .+1]
hrrzs (p)
>;ifn membug
MOVEI B,[SETZ SCMWCMA(A) ;Commands
INFILE
SCMSIZ
SETZ AUXWCMA(A) ;Read Data
RDAFLG
AUXSIZ
SETZ OUTWCMA(A) ;Write Data
OUTFILE
OUTSIZ
0] ;(end of list)
TYPLP: SKIPN @1(B) ;Is there a file there?
JRST NOFILE ; No, don't get buffers then.
MOVE A,NBUFS ;Get number of buffers to use
SUBI A,1 ;Table starts at 0, not 1
GBUFLP: SKIPE @(B) ;Is there something already there?
JRST GBUFEC ; Yes, buffer OK
CALL SNDMSG,<[MGBUF,,SIXDEV]>,<2(B)>,<[1]> ;Get a buffer
CALL MSGWAIT,<[MGBUF,,SIXDEV]> ;Wait for it
SKIPN MEMDEB ;Print memory usage?
JRST NOMMDB ; No
CALL WRASCZ↑,<[[ASCIZ/Buffer at /]]>,TYOOP
CALL WROCT↑,MSGDAT,<[6]>,TYOOP
CALL WRASCZ↑,<[[ASCIZ/ of /]]>,TYOOP
HLRE RET,MSGDAT ;Get negative of count
MOVN RET,RET
CALL WRINT↑,RET,<[8]>,TYOOP
CALL DOCRLF
NOMMDB: MOVE RET,MSGDAT ;Get WCMA
JUMPGE RET,[CALL WRASCZ↑,<[[ASCIZ/Not enough buffer space on SIX. - Aborting/]]>,TYOOP
JRST DIE]
MOVEM RET,@(B) ;Save WCMA for this buffer
GBUFEC: SOJGE A,GBUFLP ;Repeat for each buffer
NOFILE: ADDI B,3 ;Advance to next in list of things wanting buffers
SKIPE (B) ;Is this the end of the list
JRST TYPLP ; No, more buffers wanted, perhaps
ifn membug,<
skipl (p)
jrst foo2
;Give back the top of core!!!
movei ret,(p)
call sndmsg,<[mgivb,,sixdev]>,ret,<[1]>
call msgwait,<[mgivb,,sixdev]>
foo2: pop p,(p)
>;ifn membug
SETZM SCMNXT
SETZM AUXNXT
SETZM OUTNXT
;Alternate entry point to repeatedly playing
↑SAMSET:
SETZM SCMACT
SETZM SCMLST
SETZM AUXACT
SETZM OUTACT
CALL SNDMS1,<[MSTIFL,,SAMDEV]> ;Clear all processing elements
CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAGO!SCACLT!SCAUPD]]>,<[1]>
;Start running with update ticks, only
SKIPE PACKED ;Which read data format
JRST ISPACK ; Two 16 bit samples/word
CALL SNDMSG,<[MCONOB,,SAMDEV]>,<[[DR20B]]>,<[1]>
;Select one 20 bit sample/word
ISPACK: CALL SNDMSG,<[MDTA,,SAMDEV]>,<[[CLRPAS]]>,<[1]>
↑SAMST2: USETI SCMCHN,1 ;Set to beginning of file
SETZM INADR
LOADLP: CALL GETSCM,SCMSIZ ;Get a buffer, if any
JRST[ CALL ENDSCM ; EOF, put out funny trailer
JRST AUXSET]
CALL SNDSCM,RET
MOVE RET,SCMACT ;Check number of active buffers
CAMGE RET,NBUFS ;Are they all full?
JRST LOADLP ; No, more to go
AUXSET: SKIPE ADCFLG ;ADC mode?
JRST AUXLP ; Yes, skip USETI and set 'er up
;;;prints/*** For some reason, REPEAT doesn't repeat Read Data. Problem should be
;;;here but doesn't seem to be!
;;;/
SKIPN AUXFIL ;Is there something to send?
JRST OUTSET ; No, we're done
USETI AUXCHN,1 ;Set to beginning of file
AUXLP: CALL GETAUX,AUXSIZ ;Get a buffer, if any
JRST OUTSET ; OK, done
CALL SNDAUX,RET
MOVE RET,AUXACT ;Check number of active buffers
CAMGE RET,NBUFS ;Are they all full?
JRST AUXLP ; No, more to go
OUTSET: SKIPN OUTFIL ;Is there something to send?
JRST ADCSET ; No, we're done
USETO OUTCHN,1 ;Set to beginning of file
OUTLP: CALL SETOUT,OUTSIZ ;Prepare next buffer
MOVE RET,OUTACT ;Check number of active buffers
CAMGE RET,NBUFS ;Are they all full?
JRST OUTLP ; No, more to go
ADCSET: SKIPN ADCFLG ;Reading from ADC?
JRST SETRDY ; No, done
CALL SNDMSG,<[MSPAR,,ADCDEV]>,<[[400000+3*1000+1*100+42]]>,<[1]>
;Datum: (thresh + mpx),,(speed*1000 + pack*100 + SAMBIT*40 + Nchannels)
;*** Temporary packing mode
CALL MSGWAIT,<[MSPAR,,ADCDEV]> ;Wait for it
CALL SNDMS1,<[MFSTB,,ADCDEV]>
;Clear data missed flag
ADCLP: CALL SETADC,AUXSIZ ;Setup buffer for ADC
MOVE RET,ADCACT ;Are they all full?
CAMGE RET,NBUFS ;Are they all full?
JRST ADCLP ; No, more to go
SETRDY: SETOM SAMRDY ;SAM is ready to GO
SKIPN TAPEFL ;Is message needed?
POP0J ; No, just leave
CALL WRASCZ↑,<[[ASCIZ/Type GO when ready: /]]>,TYOOP
CALL TYOFLUSH
POP0J
NOSAM: CALL WRASCZ↑,<[[ASCIZ/Can't INIT SAM (it is unavailable). /]]>,TYOOP
JRST DIE
SUBREND SAMINI
NSUBR SAMGO ;Start Samson Box
skipn samrdy ;Is it ready?
;;;prints/SAMGO+1: Can get here if SAM is taken after asking for number of times to play.
;;;/]
halt . ; No? BUG!!!!!
MOVSI RET,663000+ADSSAM ;Temporarily select SAM and delay beeps
SKIPN NOMAP ;Don't map?
ADSMAP RET, ; No, really do selection
CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT!SCACLT!SCAPRO]]>,<[1]>
;Stop clock, reset tick counter and allow processing ticks
CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAGO]]>,<[1]>
;Start it running!
SETOM SAMRUN
POP0J
SUBREND SAMGO
NSUBR SIXMSG ;Process message from SIX
ifn intbug,< outchr ["6"] >
MOVE RET,MSGBUF ;Get message
AND RET,[XWD 007777,000777] ;Get only what we're interested in
MOVSI RET2,-NKNOWN ;Search list of types we know about
SEARCH: CAME RET,MSGTYP(RET2) ;Is this one of ours?
AOBJN RET2,SEARCH ; No, try next one
JUMPGE RET2,UNKNOWN ;Give up if we didn't find one
XCT MSGSUB(RET2) ;Do something about the message
DONE: POP0J ;Now, we're done
;Complain about lack of knowledge
UNKNOWN: CALL WRASCZ↑,<[[ASCIZ/Unexpected message from SIX: /]]>,TYOOP
ifn msgbug,<
CALL DOCRLF
CALL PRTMSG
>;ifn msgbug
ife msgbug,<
CALL WROCT↑,MSGBUF,<[=12]>,TYOOP
MOVEI RET,","
XCT TYOOP
CALL WROCT↑,MSGBUF+1,<[=12]>,TYOOP
CALL DOCRLF
MOVEI RET,","
XCT TYOOP
CALL WROCT↑,MSGBUF+2,<[=12]>,TYOOP
CALL DOCRLF
>;ife msgbug
JRST DONE
;Message type known here
MSGTYP: XWD MINT,SAMDEV ;Interrupt from SAM
XWD MIOV,SAMDEV ;Too many interrupts from SAM
XWD MCDONE,SAMDEV ;Command buffer done
XWD MRDONE,SAMDEV ;Read data buffer done
XWD MWDONE,SAMDEV ;Write data buffer done
XWD MCONIA,SAMDEV ;Reply to CONI-A
XWD MCONIB,SAMDEV ;Reply to CONI-B
XWD MBDONE,ADCDEV ;ADC buffer done
XWD MSTBUF,ADCDEV ;Ignore response
;Routines to handle SIX messages
MSGSUB: CALL PRMINT ;Interrupt from SAM
CALL PRMIOV ;Too many interrupts from SAM
CALL SCMDONE ;Command buffer done
CALL AUXDONE ;Read data buffer done
CALL OUTDONE ;Write data buffer done
CALL PCONIA ;Reply to CONI-A
CALL PCONIB ;Reply to CONI-B
CALL ADCDONE ;ADC buffer done
JFCL
NKNOWN←←.-MSGTYP
;Too many losing interrupts
PRMIOV: CALL WRASCZ↑,<[[ASCIZ/Too many SAM interrupts, SIX gives up remembering.
Aborting... /]]>,TYOOP
JRST DIE ;Probably safest thing
;----- MINT - Print information (Samson Box interrupt)
PRMINT: SKIPGE MSGDAT ;Get code from message
JRST[ SKIPA RET,[[ASCIZ/Interrupt on SAM channel A: /]]
PCONIA: MOVEI RET,[ASCIZ/CONI A status: /]
MOVEI T,TCONIA ;It's a CONI-A
JRST MINTL1]
SKIPA RET,[ASCIZ/Interrupt on SAM channel B: /]
PCONIB: MOVEI RET,[ASCIZ/CONI B status: /]
MOVEI T,TCONIB
MINTL1: CALL WRASCZ↑,RET,TYOOP
CALL WROCT↑,MSGDAT,<[=6]>,TYOOP
CALL DOCRLF ;Send it out and go to next line
MOVE T2,MSGDAT ;Get CONI
MOVE RET2,-1(T) ;Get first bit to examine
MINTLP: TDNE T2,RET2 ;Was this bit on?
SKIPG RET,(T) ;and is it to be printed?
JRST MINTEC ; No, do End Check
CALL WRASCZ↑,RET,TYOOP ;Print message
CALL DOCRLF ;Send it out and go to next line
MINTEC: ROT RET2,-1 ;Move to next lower bit
SKIPL (T) ;Done yet?
AOJA T,MINTLP ; No, repeat until out of messages
POP0J ;End of MINT printout
200000 ;First bit of interest
TCONIA: [ASCIZ/Command buffer exhausted/]
[ASCIZ/Write data buffer exhausted/]
[ASCIZ/Read data buffer exhausted/]
[ASCIZ/Delay memory parity error/]
[ASCIZ/SIX memory parity error/]
[ASCIZ/Non-existant (SIX) memory/]
[ASCIZ/SAM Running/]
[ASCIZ/Not being held/]
[ASCIZ/Command underrun/]
[ASCIZ/Write data underrun/]
[ASCIZ/Read data underrun/]
-1
100000 ;First bit of interest
TCONIB: [ASCIZ/Command overrun/] ;100000
[ASCIZ/Mod. Mixer Overflow/] ;040000
[ASCIZ/Mod. Multiplier Overflow/] ;020000
[ASCIZ/Mod. Sum Memory Overflow/] ;010000
[ASCIZ/Gen. Sum Memory Overflow/] ;004000
0 ;002000
[ASCIZ/'Lost Cause'/] ;001000
-1
;----- MCDONE - Command buffer done (send another)
SCMDONE:
;;; PRINTS/Command buffer done routine could use some work.
;;;/
ifn intbug,< outchr ["!"] >
SKIPN SAMRUN ;Running?
JRST[ CALL WRASCZ↑,<[[
ASCIZ/Bug: Cmd Buffer done seen with SAMRUN false!/]]>,TYOOP
CALL DOCRLF
POP0J ]
SOS SCMACT ;Decrement number of active command buffers
SKIPE SCMLST ;Last buffer sent yet?
JRST[ SKIPE SCMACT ; Yes, check for end of whole thing
POP0J ; still some buffers left
;;; SKIPN RDTACT ; Read data active?
;;; SKIPE WDTACT ; Write data active?
;;; POP0J ; Yes, not done yet
;; prints/Wait feature goes here.
;;/
SOSLE RPTCNT ; Any repeats left?
JRST[ SETZM SCMLST ;No longer at last buffer
;;; CALL SAMSET ; Start at beginning after reseting
call samst2 ; Just start from beg. of file for now
POP0J ]
SETZM SAMRUN ; No longer running
SETZM SAMRDY ; No longer ready
MOVSI RET,663000+ADSSAM ;Select for 1/4 second longer
ADDI RET,1
SKIPN NOMAP ;Don't map?
ADSMAP RET, ; No, really do selection
SKIPE MAILBOX+MLINT ;Interrupt requested?
CALL SNDINT ; Send interrupt
SKIPE ONCE ; Play once more, only?
JRST DIE ; Yes, then we're done!
SKIPN GRABBY ; Hold onto box?
RELEASE SAMCHN, ; No, Let other users go
SKIPE LOCKFL ; Locked in core?
UNLOCK ; Yes, flush that
CALL WRASCZ↑,<[[ASCIZ/
Number of times to play: /]]>,TYOOP
CALL TYOFLUSH
POP0J] ; Done!!
CALL GETSCM,SCMSIZ ;Get a buffer size, if any commands left
JRST[ CALL ENDSCM ; EOF, put out funny trailer
POP0J]
CALL SNDSCM,RET ;Send it to SAM
POP0J ;Done and ready for next one
;----- MRDONE - Read data done (send another)
AUXDONE:
SKIPN SAMRUN ;Running?
JRST[ CALL WRASCZ↑,<[[
ASCIZ/Bug: Read Buffer done seen with SAMRUN false!/]]>,TYOOP
CALL DOCRLF
POP0J ]
SOS AUXACT ;Decrement number of active command buffers
CALL GETAUX,AUXSIZ ;Get a buffer size, if any data left
POP0J ; Nothing left, forget it
CALL SNDAUX,RET ;Send it to SAM
POP0J ;Done and ready for next one
;----- MWDONE - Write data done (send to disk and setup next)
OUTDONE:
SKIPN SAMRUN ;Running?
JRST[ CALL WRASCZ↑,<[[
ASCIZ/Bug: Write Buffer done seen with SAMRUN false!/]]>,TYOOP
CALL DOCRLF
POP0J ]
SOS OUTACT ;Decrement number of active command buffers
CALL SNDOUT,OUTSIZ ;Write out buffer from SAM to disk
CALL SETOUT,OUTSIZ ;Setup buffer for SAM
POP0J ;Done and ready for next one
;----- ADCDONE - ADC buffer done (send another)
ADCDONE:
SKIPN SAMRUN ;Running?
JRST[ CALL WRASCZ↑,<[[
ASCIZ/Bug: ADC Buffer done seen with SAMRUN false!/]]>,TYOOP
CALL DOCRLF
POP0J ]
SOS AUXACT ;Decrement number of active command buffers
CALL SETADC,AUXSIZ ;Setup buffer for ADC
POP0J ;Done and ready for next one
SUBREND SIXMSG
NSUBR MSGWAIT,CODE ;Wait for specified message type
;or other interrupt condition
PUSHP A
ifn intbug,< outchr ["<"] ;Fudge for matching brackets ">"
>;ifn intbug
IFN TMOENB,<
CLKINT [2*=60*=60] ;Wait 2 minute(s) before giving up
>;IFN TMOENB
MSGWLP: CALL WAITON,<[INTTTY!INTMAIL!INTCLK!INTTTI!INTSIX]]>
MOVE A,RET ;Save interrupt conditions
TLNE A,(INTTTI)
JRST[ CALL WRASCZ↑,<[[ASCIZ/<esc>I interrrupt - Aborting/]]>,TYOOP
JRST DIE]
TLNE A,(INTTTY) ;TTY input?
CALL ALTCHK ; Yes, check for <altmode>
TRNN A,INTSIX ;SIX message?
JRST OTHER ; No, some other flavor of interrupt
CALL RCVMSG ;Get the message
MOVEI A,INTSIX
ANDCAB A,PENDING
CAMN RET,CODE ;Is it the one we want?
JRST DONE ; Yes, done
ifn intbug,< outchr ["="] >
CALL SIXMSG ;No, process a general message
OTHER: TLNE A,(INTMAIL) ;Mail received?
JRST[ CALL RDMAIL ; Yes, read it
JRST MSGWLP] ; Go back for more
TLNE A,(INTCLK)
JRST[ CALL WRASCZ↑,<[[ASCIZ/Timeout - Aborting/]]>,TYOOP
JRST DIE]
JUMPE A,MSGWLP ;All interrupts serviced
CALL WRASCZ↑,<[[ASCIZ/Unexpectd return from WAITON, ignoring./]]>,TYOOP
CALL DOCRLF
JRST MSGWLP
DONE: POPP A
ifn intbug,< ;Fudge for matching brackets "<"
outchr [">"]
>;ifn intbug
POP1J
SUBREND MSGWAIT
NSUBR GETSCM,COUNT ;Get SCM buffer (also GETAUX)
MOVE RET,INADR ;Get address in file
CAML RET,INWC ;Are there any words left in file?
JRST FAIL ; No, failure (non-skip) return
MOVE RET,COUNT ;Get number of words
ADDB RET,INADR ;Advance pointer in file
MOVN RET,RET ;Subtract from word count
ADD RET,INWC ;See how far we are from end of file
SKIPL RET ;Did we hit EOF?
SETZ RET, ; No, we don't have to fudge
ADDM RET,INADR ;Fudge in case of end of file
ADD RET,COUNT ;Calculate number of words to read
AOS (P) ;Take success (skip) return
FAIL: POP1J
SUBREND GETSCM
NSUBR GETAUX,COUNT ;Get AUX buffer
SKIPE ADCFLG ;Using ADC?
JRST[ MOVE RET,COUNT ; Yes, always use whole buffer
JRST ALWAYS ]
MOVE RET,AUXADR ;Get address in file
CAML RET,AUXWC ;Are there any words left in file?
JRST FAIL ; No, failure (non-skip) return
MOVE RET,COUNT ;Get number of words
ADDB RET,AUXADR ;Advance pointer in file
MOVN RET,RET ;Subtract from word count
ADD RET,AUXWC ;See how far we are from end of file
SKIPL RET ;Did we hit EOF?
SETZ RET, ; No, we don't have to fudge
ADDM RET,AUXADR ;Fudge in case of end of file
ADD RET,COUNT ;Calculate number of words to read
ALWAYS: AOS (P) ;Take success (skip) return
FAIL: POP1J
SUBREND GETAUX
NSUBR SNDSCM,COUNT ;Send command buffer to SAM (also SNDAUX)
MOVN RET,COUNT ;Make a WCMA out of this
MOVS RET,RET
MOVE RET2,SCMNXT ;Get next buffer
HRR RET,SCMWCMA(RET2) ;Set address of buffer
MOVEM RET,DSKTO6+2 ;Set in MTAPE block for disk read into P3
MOVEM RET,TMPWCMA ;Store temporarily
SOS DSKTO6+2 ;Turn WCMA into IOWD
MTAPE SCMCHN,DSKTO6 ;Read into P3's memory!!!!!
;;; halt . ;**** Temporary ****
HRRZ RET,DSKTO6+4 ;errors?
SUB RET,DSKTO6+3
JUMPN RET,[SKIPL DSKTO6+4 ;Correctable?
jrst[ outstr[asciz/Disk error into SIX memory. /]
halt .]
outstr[asciz/Correctable disk error in command channel.
/] CALL SNDMSG,<[MECC,,SYSDEV]>,<[ECCTAB]>,RET
CALL MSGWAIT,<[MECC,,SIXDEV]> ;Wait for acknowledge
JRST .+1 ]
CALL SNDMSG,<[MCBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]>
;Tell SIX to send this to SAM
AOS RET,SCMNXT ;Advance to next buffer
CAML RET,NBUFS ;End of buffer right?
SETZM SCMNXT ; Yes, start at beginning
AOS SCMACT ;Increment number of active buffers
POP1J
SUBREND SNDSCM
NSUBR SNDAUX,COUNT ;Send data buffer to SAM
MOVN RET,COUNT ;Make a WCMA out of this
MOVS RET,RET
MOVE RET2,AUXNXT ;Get next buffer
HRR RET,AUXWCMA(RET2) ;Set address of buffer
MOVEM RET,DSKTO6+2 ;Set in MTAPE block for disk read into P3
MOVEM RET,TMPWCMA ;Store temporarily
SKIPE ADCFLG ;For ADC?
JRST SKIPRD
SOS DSKTO6+2 ;Turn WCMA into IOWD
MTAPE AUXCHN,DSKTO6 ;Read into P3's memory!!!!!
;;; halt . ;**** Temporary ****
;;;PRINTS/Error recovery for MTAPE to read into P3 not tested yet.
;;;/
HRRZ RET,DSKTO6+4 ;errors?
SUB RET,DSKTO6+3
JUMPN RET,[SKIPL DSKTO6+4 ;Correctable?
jrst[ outstr[asciz/Disk error into SIX memory. /]
halt .]
outstr[asciz/Correctable disk error in read data channel.
/] CALL SNDMSG,<[MECC,,SYSDEV]>,<[ECCTAB]>,RET
CALL MSGWAIT,<[MECC,,SIXDEV]> ;Wait for acknowledge
JRST .+1 ]
SKIPRD: CALL SNDMSG,<[MRDBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]>
;Tell SIX to send this to SAM
AOS RET,AUXNXT ;Advance to next buffer
CAML RET,NBUFS ;End of buffer right?
SETZM AUXNXT ; Yes, start at beginning
AOS AUXACT ;Increment number of active buffers
POP1J
SUBREND SNDAUX
NSUBR SETOUT,COUNT ;Send data buffer to SAM (also SNDOUT)
MOVN RET,COUNT ;Make a WCMA out of this
MOVS RET,RET
MOVE RET2,OUTNXT ;Get next buffer
HRR RET,OUTWCMA(RET2) ;Set address of buffer
MOVEM RET,TMPWCMA ;Store temporarily
CALL SNDMSG,<[MWDBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]> ;Tell SIX to send this to SAM
AOS RET,OUTNXT ;Advance to next buffer
CAML RET,NBUFS ;End of buffer right?
SETZM OUTNXT ; Yes, start at beginning
AOS OUTACT ;Increment number of active buffers
POP1J
SUBREND SETOUT
NSUBR SNDOUT,COUNT ;Send data buffer to disk
MOVN RET,COUNT ;Make a WCMA out of this
MOVS RET,RET
MOVE RET2,OUTNXT ;Get next buffer
HRR RET,OUTWCMA(RET2) ;Set address of buffer
MOVEM RET,DSKFR6+2 ;Set in MTAPE block for disk read into P3
SOS DSKFR6+2 ;Turn WCMA into IOWD
MTAPE OUTCHN,DSKFR6 ;Write from P3's memory!!!!!
;;; halt . ;**** Temporary ****
POP1J
SUBREND SNDOUT
NSUBR SETADC,COUNT ;Send data buffer to ADC
MOVN RET,COUNT ;Make a WCMA out of this
MOVS RET,RET
MOVE RET2,ADCNXT ;Get next buffer
HRR RET,AUXWCMA(RET2) ;Set address of buffer
MOVEM RET,TMPWCMA ;Store temporarily
CALL SNDMSG,<[MSTBUF,,ADCDEV]>,<[TMPWCMA]>,<[1]>
;Tell SIX to send this to ADC
AOS RET,ADCNXT ;Advance to next buffer
CAML RET,NBUFS ;End of buffer right?
SETZM ADCNXT ; Yes, start at beginning
AOS ADCACT ;Increment number of active buffers
POP1J
SUBREND SETADC
NSUBR ENDSCM ;Send special trailer buffer to SAM
MOVEI RET,SCMNOP ;Use NOP as trailer
MOVEM RET,MSGDAT+1
MOVE RET,[XWD MSGDAT+1,MSGDAT+2]
IFG TAILSZ-MSGMSZ-2,< .FATAL /Message buffer won't hold trailer!
/>
BLT RET,MSGDAT+TAILSZ ;Make a buffer full of NOPs
MOVE RET2,SCMNXT ;Get next buffer
MOVSI RET,-TAILSZ
HRR RET,SCMWCMA(RET2) ;Set address of buffer
MOVEM RET,MSGDAT
PUSHP RET ;Save WCMA over MSGWAIT
CALL SNDMSG,<[MWMEM,,SIXDEV]>,<[0]>,<[1+TAILSZ]>
;Put special trailer in next buffer
CALL MSGWAIT,<[MWMEM,,SIXDEV]> ;Wait for acknowledge
POPP MSGDAT ;Get back WCMA for sending to SAM
CALL SNDMSG,<[MCBUF,,SAMDEV]>,<[MSGDAT]>,<[1]>
;Tell SIX to send this to SAM
SETOM SCMLST ;Mark as last buffer
AOS RET,SCMNXT ;Advance to next buffer
CAML RET,NBUFS ;End of buffer right?
SETZM SCMNXT ; Yes, start at beginning
AOS SCMACT ;Increment number of active buffers
POP0J
SUBREND ENDSCM
NSUBR RCVMSG ;Recieve message from SIX
INPUT SIXCHN,[IOWD MSGMSZ,MSGBUF]
ifn msgbug,<
skipe debug
call prtmsg
>;ifn msgbug
MOVE RET,MSGBUF ;Return code for message
AND RET,[XWD 007777,000777] ;Return only code and source
POP0J
SUBREND RCVMSG
NSUBR SNDMSG,CODE,DATA,SIZE ;Send message to SIX (device)
MOVE RET,CODE ;Set code for message
TLNN RET,777 ;Make sure there is a code there
PUSHJ P,[
BADARG: PUSHP RET
CALL WRASCZ↑,<[[ASCIZ/Bad call to SNDMSG./]]>,TYOOP
CALL DOCRLF
POPP RET
HALT .]
MOVEM RET,MSGBUF
MOVE RET,THISJOB ;Set this job's number
DPB RET,[POINT 9,MSGBUF,26]
AOS RET,SEQNUM ;Put in sequence number
ANDI RET,377777
HRL RET,SIZE ;Include number of data words
MOVEM RET,MSGBUF+1
HRLZ RET,DATA ;Get address of buffer
HRRI RET,MSGDAT
MOVE RET2,SIZE ;Get size of block
CAILE RET2,MSGMSZ-2 ;Check buffer size
PUSHJ P,BADARG
TLNE RET,-1 ;Are we to inhibit copy of buffer?
SKIPN RET2 ;Or is it a zero word count?
JRST SKPBLT ; Yes, don't copy data!
BLT RET,MSGDAT-1(RET2) ;Copy data into buffer
SKPBLT: ADDI RET2,2 ;Add in overhead
MOVN RET2,RET2 ;Make an IOWD
HRLZ RET2,RET2
HRRI RET2,MSGBUF-1
OUTPUT SIXCHN,RET2 ;Actually send message to SIX system
ifn msgbug,<
skipe debug
call prtmsg
>;ifn msgbug
POP3J ;Flush args and return
SUBREND SNDMSG
NSUBR SNDMS1,CODE ;Send one word message to SIX (device)
MOVE RET,CODE ;Set code for message
TLNN RET,777 ;Make sure there is a code there
PUSHJ P,[
BADARG: CALL WRASCZ↑,<[[ASCIZ/Bad call to SNDMSG./]]>
CALL DOCRLF
HALT .]
MOVEM RET,MSGBUF
MOVE RET,THISJOB ;Set this job's number
DPB RET,[POINT 9,MSGBUF,26]
OUTPUT SIXCHN,[IOWD 1,MSGBUF]
ifn msgbug,<
skipe debug
call prtmsg
>;ifn msgbug
POP1J
SUBREND SNDMS1
NSUBR PRTMSG ;Print message
MOVE RET2,MSGBUF
MOVEI RET,[ASCIZ/Xmt /]
TLNE RET2,F6TO10
MOVEI RET,[ASCIZ/Rcv /]
CALL WRASCZ↑,RET,TYOOP
TLNN RET2,FNCOMP
JRST L1
CALL WRASCZ↑,<[[ASCIZ/Data_error /]]>,TYOOP
L1: TLNN RET2,FDMISS
JRST L2
CALL WRASCZ↑,<[[ASCIZ/Data_missed /]]>,TYOOP
L2:
LDB RET,[POINT 12,MSGBUF,17]
LDB RET2,[POINT 9,MSGBUF,35]
CALL WRMSGN↑,RET,RET2,TYOOP
CALL WRASCZ↑,<[[ASCIZ/ Job /]]>,TYOOP
LDB RET,[POINT 9,MSGBUF,26]
CALL WRINT↑,RET,<[=10]>,TYOOP
LDB RET,[POINT 9,MSGBUF,35]
CAIL RET,NDEVS
SETO RET,
CALL WRSIX↑,DVNAMS(RET),TYOOP
TLNE RET2,FNOWDS ;One word message?
JRST DONE ; Yes, done
HLRZ RET,MSGBUF+1 ;Get count
CALL WRINT,RET,<[8]>,TYOOP ;Print word count
CALL WRASCZ↑,<[[ASCIZ/ wds #/]]>,TYOOP
HRRZ RET,MSGBUF+1
CALL WROCT↑,RET,<[6]>,TYOOP
MOVEI RET,"I"-"@" ;tab
XCT TYOOP
CALL WROCT↑,MSGDAT,<[=12]>,TYOOP
DONE: CALL DOCRLF
POP0J
SIXBIT / ??? /
DVNAMS: SIXBIT / SIX /
SIXBIT / SAM /
SIXBIT / DAC /
SIXBIT / ADC /
SIXBIT / FRM /
SIXBIT / KIM /
SIXBIT / RTJ /
NDEVS←←.-DVNAMS
SUBREND PRTMSG
NSUBR WAITON,CONDITIONS ;Wait for one of several events
ifn intbug,< outchr ["W"]>
;Following code is complicated by the fact that you can recieve more
;than one interrupt per SIX message, and that we still want to know
;if we have gotten other interrpts.
MOVEI RET,INTSIX ;Setup bit from SIX interrupts
TDNN RET,CONDITIONS ;Is it a condition we are waiting for?
JRST DOWAIT ; No, just wait.
MTAPE SIXCHN,SIXMTA ;Is there a message pending?
JRST DOWAIT ; No, wait for something
ORM RET,PENDING ;Yes, process it
INTIRQ RET, ;Get pending interrupts
TDNE RET,CONDITIONS ;Skip if none need to be ack'ed to system
DOWAIT: IMSTW CONDITIONS ;Enable interrupts and wait for one
MOVE RET,PENDING ;Get conditions
AND RET,CONDITIONS ;Return any relevant ones
POP1J
SUBREND WAITON
;----- INTSER ;Interrupt service routine
INTSER: INTMSK [0] ;Clear interrupt mask
MOVE RET,JOBCNI ;OR conditions into those which haven't
ORM RET,PENDING ;been processed at user level
DISMIS ;And done (this shouldn't even have to
;be done at interrupt level!!!!!)
NSUBR SNDINT ;Send interrupt to calling program
MOVE RET,MAILBOX+MLJOB ;Setup block for UUO
MOVE RET+1,MAILBOX+MLINT
INTIPI RET ;Send the interrupt
JFCL ; Ignore it if it fails
POP0J
SUBREND SNDINT
NSUBR SWNUM ;Get number from switch name (from FCOPY)
SWNUM: CALL(RDSIX↑,<[PUSHJ P,CMDGET]>,[SWBRK])
COMMENT ⊗
MOVSI 2,-SWCNT
CAME 1,SWTAB(2)
AOBJN 2,.-1
JUMPGE 2,[FATAL(Unknown switch)]
HRRZ 2,2
POP0J
⊗;
SETZM SWMATCH# ;Number of matches less one
SKIPN 3,1 ;Make sure switch was given and save switch
JRST SWUNKN
MOVSI 2,(<POINT 6,0,35>);Turn spaces (00) into (77)
SWNUM2: ILDB 4,2
JUMPN 4,NOTSPA
MOVEI 4,77
DPB 4,2
NOTSPA: CAME 2,[POINT 6,1,35] ;All of word done?
JRST SWNUM2 ;No
SETCM 4,1 ;Compliment it
MOVSI 2,-SWCNT
;2 now contains AOBJN pointer for switchs
;3 now contains bits which must be on to recognize switch name
;4 now contains bits which must be off to recognize switch name
SWNUM3: TDNE 4,SWTAB(2) ;All bits off that need be?
AOBJN 2,SWNUM3 ;No, try again (if more, else continue and fail later)
SETCM 1,SWTAB(2) ;Pick up compliment of switch
TDNN 2,1 ;All needed bits on?
SWNUM4: AOBJN 2,SWNUM3 ;No, try again (if more, else continue and fail later)
SKIPE SWMATCH ;Previous match?
JRST [ JUMPL 2,[CALL WRASCZ↑,<[[ASCIZ/Ambiguous switch/]]>,TYOOP
JRST DIE] ;And if not end, lose
HRRZ 2,SWMATCH ;Return match
POPJ P,]
MOVEM 2,SWMATCH ;Save last match
JUMPL 2,SWNUM4 ;And go back for more, unless already at end of list
SWUNKN: CALL WRASCZ↑,<[[ASCIZ/Unknown switch. /]]>
JRST DIE
;Break table for reading switches
SWBRK: BYTE (32) -1 (1) 0 (3) -1 ;<null> thru #
BYTE (2) 0 (10) -1 (10) 0 (6) -1 (1) -1 (7) 0 ;$ thru G
BYTE (19) 0 (5) -1 (1) -1 (11) 0 ;H thru k
BYTE (15) 0 (5) -1 (16) 0 ;l thru <bs>
SUBREND SWNUM
;Typeout to arbitrary TTY, using NULMES
TYOOP: PUSHJ P,PUTCHR
PUTCHR: SOSLE TYOLFT ;Space left in buffer
JRST[ IDPB 1,TYOPTR ;Stuff character in output buffer
POPJ P,] ;And return
PUSHJ P,TYOFLU ; No, output it to get some more
JRST PUTCHR
HALT PUTCHR
TYOFLU: PUSH P,1 ;Save register
MOVE 1,[POINT 7,TYOBUF] ;Reset pointer to beginning of buffer
MOVEM 1,TYOPTR ;Setup pointer for NULMES
MOVEI 1,TYOSIZ ;Calculate count
SUB 1,TYOLFT
JUMPE 1,PUTOU9 ;If nothing to do, skip it!
DPB 1,[POINT 12,TYOPTR,17]
PUSH P,1 ;Save count on stack
PUTOU2: MOVEI 1,TYOTTY ;Setup UUO block for NULMES
NULMES 1,
JRST[ JUMPE 1,PUTOU9 ;*** No one home if none left to print????
PUSH P,1 ;Save count left on stack
MOVE 1,-1(P) ;Get original count
SUB 1,(P) ;this gives number of characters sent
JUMPE 1,[MOVEI 1,=3 ;Holding, wait a while this time
SLEEP 1,
JRST PUTOU2]
PUSH P,2 ;IDIV will clobber AC 2
IDIVI 1,5 ;Convert byte count into word count and
;remainder
ADDM 1,TYOPTR ;Increment word part of pointer
SKIPE 2 ;Skip over first decrement if exact word count
PUTOU3: IBP TYOPTR ;Increment pointer for each in remainder
SOJG 2,PUTOU3
POP P,-1(P) ;Put new count where old count was
MOVEI 1,1 ;Sleep a second
SLEEP 1,
JRST PUTOU2]
PUTOU9: POP P,1 ;Flush stack
MOVEI 1,TYOSIZ ;Set number of characters left
MOVEM 1,TYOLFT
MOVE 1,[POINT 7,TYOBUF] ;Reset pointer to beginning of buffer
MOVEM 1,TYOPTR ;Setup pointer for NULMES
POP P,1
POPJ P,
;Output a CRLF and flush out buffer
DOCRLF: MOVEI 1,15 ;CR
PUSHJ P,PUTCHR
MOVEI 1,12 ;LF
PUSHJ P,PUTCHR
PUSHJ P,TYOFLUSH ;Force out line
POPJ P,
;Get character from command string. This could also be made to read
;from a command file
CMDGET: INCHWL 1 ;Get a character, activate on end of line
SOS RESCNT ;For initialization
POPJ P,
;Data area
BEGZER:: ;Beginning of area zeroed on (re)initialization
SCMWCMA: BLOCK MAXBFS ;Buffer addresses in SIX (in WCMA form)
AUXWCMA: BLOCK MAXBFS ;Buffer addresses in SIX (in WCMA form)
OUTWCMA: BLOCK MAXBFS ;Buffer addresses in SIX (in WCMA form)
TMPWCMA: BLOCK 1 ;Use to store partial WCMA prior to SNDMSG
SCMNXT: BLOCK 1 ;Next buffer for commands
SCMACT: BLOCK 1 ;Number of buffers active
SCMLST: BLOCK 1 ;Flag indicating trailing buffer has been sent
AUXNXT: BLOCK 1 ;Next buffer for read data
AUXACT: BLOCK 1 ;Number of buffers active
OUTNXT: BLOCK 1 ;Next buffer for write data
OUTACT: BLOCK 1 ;Number of buffers active
ADCFLG: BLOCK 1 ;If non-zero, then reading data from ADC, not DSK
ADCNXT: BLOCK 1 ;Next buffer for ADC data
ADCACT: BLOCK 1 ;Number of buffers active
RDAFLG: BLOCK 1 ;Read data in use
SAMRDY: BLOCK 1 ;Flag indicating SAM ready to run
SAMRUN: BLOCK 1 ;Flag indicating SAM is already running
WAITIME: BLOCK 1 ;If non-negative, number of seconds to wait
;between plays
RPTCNT: BLOCK 1 ;Number of times left to play
ONCE: BLOCK 1 ;If nonzero, play once and then leave
WAITFL: BLOCK 1 ;Always wait
NOMAP: BLOCK 1 ;Disable mapping of console speaker
GRABBY: BLOCK 1 ;Hold onto Box between plays
TAPEFL: BLOCK 1 ;Taping (don't start until GO)
MEMDEB: BLOCK 1 ;Print memory buffer addresses (if non-zero)
LOCKFL: BLOCK 1 ;Lock job in core during play (or tape)
PACKED: BLOCK 1 ;Packed (16 bit) (if non-zero)
OVERWR: BLOCK 1 ;Overwrite output file
THISJOB: BLOCK 1 ;This job's numer
;Message buffer for SIX
;↓↓↓ NEXT TWO LINES MUST BE KEPT IN ORDER
MSGBUF: BLOCK 2 ;Header for SIX message
MSGDAT: BLOCK MSGMSZ ;Data for SIX message
;↑↑↑ PREVIOUS TWO LINES MUST BE KEPT IN ORDER
;Pending interrupts
PENDING: BLOCK 1
;Buffer for messages from controlling program (if run detached)
MAILBOX: BLOCK =32
;Special block for SIX MTAPE (to see if anything is waiting)
SIXMTA: BLOCK 2
;Type out buffer
TYOLFT: 0 ;Number of characters left in buffer
TYOTTY: -1 ;TTY number to use
TYOPTR: 0 ;Pointer to buffer
TYOBUF: BLOCK =80/5 ;Type out buffer
TYOSIZ←← 5*(.-TYOBUF) ;Length of type out buffer
ENDZER←←.-1
;Parameters controlling buffer allocation
NBUFS: 3 ;Number of buffers to use (default 3)
SCMSIZ: =9*=128 ;Size of SCM buffer on SIX
AUXSIZ: =2*=18*=128 ;Size of AUX buffer on SIX
OUTSIZ: =18*=128 ;Size of OUT buffer on SIX
SEQNUM: 0 ;Sequence number for next message
;Input specification block for RDFILN, OPEN and LOOKUP
INBLK: 17 ;Device mode
INDEV: SIXBIT/DSK/ ;Device name
XWD 0,INHDR ;Pointers to buffer headers
INFILE: SIXBIT/TEST/ ;SIXBIT/Filename/
SIXBIT/SAM/ ;SIXBIT/Extension/ (Other info. returned in right half)
BLOCK 1 ;(Date and protection returned here)
BLOCK 1 ;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
;;INFILE: BLOCK 1 ;SIXBIT/Filename/
;; BLOCK 1 ;SIXBIT/Extension/ (Other info. returned in right half)
;; BLOCK 1 ;(Date and protection returned here)
;; BLOCK 1 ;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
;Negative swapped length returned here by LOOKUP
;Input buffer header for OPEN, IN
INHDR: BLOCK 3
;Addressing
INWC: BLOCK 1 ;Number of words in file
INADR: BLOCK 1 ;Current address in file
;Read data specification block for RDFILN, OPEN and LOOKUP
AUXBLK: 17 ;Device mode
AUXDEV: SIXBIT/DSK/ ;Device name
XWD 0,AUXHDR ;Pointers to buffer headers
AUXFIL: BLOCK 1 ;SIXBIT/Filename/
BLOCK 1 ;SIXBIT/Extension/ (Other info. returned in right half)
BLOCK 1 ;(Date and protection returned here)
BLOCK 1 ;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
;Negative swapped length returned here by LOOKUP
;Input buffer header for OPEN, IN
AUXHDR: BLOCK 3
;Addressing
AUXWC: BLOCK 1 ;Number of words in file
AUXADR: BLOCK 1 ;Current address in file
;Output specification block for RDFILN, OPEN and LOOKUP
OUTBLK: 17 ;Device mode
OUTDEV: SIXBIT/DSK/ ;Device name
XWD 0,OUTHDR ;Pointers to buffer headers
OUTFIL: BLOCK 1 ;SIXBIT/Filename/
BLOCK 1 ;SIXBIT/Extension/ (Other info. returned in right half)
BLOCK 1 ;(Date and protection returned here)
BLOCK 1 ;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
;Negative swapped length returned here by LOOKUP
;Input buffer header for OPEN, IN
OUTHDR: BLOCK 3
;Special MTAPE block for writing from SIX memory
DSKFR6: SIXBIT /GODMOD/
25 ;Write disk in dump mode into P3 memory
0 ;IOWD in P3 memory
0 ;Special addressing for old-mode UDP
;Special MTAPE block for reading into SIX memory
DSKTO6: SIXBIT /GODMOD/
24 ;Read disk in dump mode into P3 memory
0 ;IOWD in P3 memory
ECCTAB ;Table for ECC (error correct code) data
0 ;ECC status word 1
0 ;ECC status word 2
0 ;Special addressing for old-mode UDP
ECCTAB: BLOCK =38 ;Table to hold error correction information
;Rescan count
RESCNT: BLOCK 1
;Debug
DEBUG: 0
;Patch areas are good for you
PATCH↑: BLOCK 40
;Pushdown List (or Stack)
PDL: BLOCK 40
PDLIOW: IOWD .-PDL,PDL ;By putting this immediately after PDL, one
;can find the beginning just from P. Used
;to print backtrace (a la LISP)
END